home *** CD-ROM | disk | FTP | other *** search
/ Software Vault: The Gold Collection / Software Vault - The Gold Collection (American Databankers) (1993).ISO / cdr49 / 134_01.zip / CPROFIL2.CSM < prev    next >
Text File  |  1993-06-12  |  12KB  |  511 lines

  1. ;    BDS `C' Profiler - Assembly Language portion
  2.  
  3. ;    Copyright (c) 1983 by Kevin B. Kenny.
  4. ;    Released to the BDS `C' Users' Group for non-commercial distribution.
  5.  
  6. ;    This file contains the assembly-language functions needed by the BDS
  7. ; `C' profiler program.
  8.  
  9. ;    Functions included:
  10.  
  11. ;    superv    chain    nexecl
  12.  
  13.     MACLIB    "BDS"
  14.  
  15. SECSIZ    EQU    128            ; Disk sector size in CP/M
  16.  
  17. ; SUPERV -- Run-time supervisor for profiler
  18.  
  19. ;    The folowing function must *NOT* be called from the 'C' program.  It
  20. ; contains the code for the profiler which is loaded into high memory while
  21. ; the profiled program is executing.  The code intercepts the RST 6 operations
  22. ; that delineate the source statements, and accumulates the totals.  Upon any
  23. ; attempt to warm-boot CP/M, the supervisor reloads CPROFILE and transfers to
  24. ; it to do the analysis and print the results.
  25.  
  26.     FUNCTION     superv
  27.  
  28. ;    The following locations are fixed offsets from the beginning of SUPERV,
  29. ; used for communication with CPROFILE itself.  Their order and size must not
  30. ; be changed without changing CPROFILE as well.
  31.  
  32. START    jmp    $-$            ; Imitation BDOS entry to mark top of
  33.                     ; available memory.  Transfers to real
  34.                     ; BDOS for processing.
  35.  
  36.     db    'cprofile', 0        ; Signature, used by CPROFILE to detect
  37.                     ; that he's been reloaded.
  38.  
  39.     jmp    preinit            ; Transfer to preliminary init code.
  40.  
  41.     jmp    fakeboot        ; Transfer to artificial warmboot
  42.                     ; routine.
  43.  
  44.     dw    suptop            ; Size of the supervisor
  45.  
  46.     dw    table            ; Pointer to first profile table entry.
  47. tbnext:
  48.     dw    table            ; Pointer to next available slot for
  49.                     ; profile table entry.
  50.  
  51. realboot:
  52.     dw    $-$            ; BIOS warm-boot entry before CPROFILE
  53.                     ; was invoked.
  54.  
  55. cmdline:
  56.     ds    128            ; CPROFILE command tail, used to reload
  57.                     ; CPROFILE.
  58.  
  59. ;    Come here on preliminary initialization after reading the target
  60. ; program into the lower TPA.  Dummy up a CCP stack pointer, clobber the
  61. ; "khack" portion of C.CCC initialization, and go re-initialize C.CCC for
  62. ; the target program.
  63.  
  64. preinit:
  65.     lxi    sp, preinit        ; Fake a stack pointer for target
  66.     mvi    a, 0C9h    ; (RET)        ; Save a return instruction in "khack"
  67.     sta    khack
  68.     mvi    a, 0C3h    ; (JMP)        ; Set up the RST 6 vector for profiling
  69.     sta    00030h
  70.     lxi    h, rst6ent
  71.     shld    00031h
  72.  
  73.     mvi    c, pstrng        ; Print message that we got here.
  74.     lxi    d, entrmsg
  75.     call    start
  76.  
  77.     call    tpa            ; Go enter the user program.
  78.  
  79.     jmp    fakeboot        ; Reload profiler when program finishes
  80.  
  81. ;    Come here on a RST 6 instruction within the target program.  Accumulate
  82. ; the profile data.
  83.  
  84. rst6ent:
  85.     push    h            ; Save all registers
  86.     push    d
  87.     push    b
  88.     push    psw
  89.  
  90.     lxi    h, 8            ; Increment return address around
  91.     dad    sp            ; line and statement information.
  92.     mov    c,m
  93.     inx    h
  94.     mov    b,m
  95.     inx    b
  96.     inx    b
  97.     mov    m,b
  98.     dcx    h
  99.     mov    m,c
  100.     dcx    h
  101.     dcx    b
  102.     dcx    b            ; Get original PC back
  103.  
  104.     lhld    tbnext
  105.     xchg                ; Get start and end of profile table
  106.     lxi    h, table
  107.  
  108. ploop:    mov    a, d            ; If at end of table, go to NOTFND
  109.     cmp    h
  110.     jnz    notdone
  111.     mov    a,e
  112.     cmp    l
  113.     jz    notfnd
  114.  
  115. notdone:
  116.     mov    a,c            ; If the PC in table doesn't match ours
  117.     cmp    m            ; go to NOTHERE(2) to advance to next
  118.     jnz    nothere         ; table entry.
  119.     inx    h
  120.     mov    a,b
  121.     cmp    m
  122.     jnz    nothere2
  123.  
  124.     lxi    b,4            ; Point HL to least significant byte of
  125.     dad    b            ; execution count
  126.  
  127.     mov    a,m
  128.     adi    1            ; Increment trip count
  129.     mov    m,a
  130.     dcx    h
  131.     mov    a,m
  132.     aci    0
  133.     mov    m,a
  134.     dcx    h
  135.     mov    a,m
  136.     aci    0
  137.     mov    m,a
  138.     dcx    h
  139.     mov    a,m
  140.     aci    0
  141.     mov    m,a
  142.  
  143.     jmp    finis            ; Done with this RST 6
  144.  
  145. nothere:
  146.     inx    h            ; Advance to next table entry
  147. nothere2:
  148.     inx    h
  149.     inx    h
  150.     inx    h
  151.     inx    h
  152.     inx    h
  153.     jmp    ploop
  154.  
  155. notfnd:
  156.     lda    start+1
  157.     sui    6
  158.     sub    l            ; Entry not found in table.  Make sure
  159.     lda    start+2            ; there's space for it.
  160.     sbb    h
  161.     jnc    addent
  162.  
  163.     mvi    c,pstrng        ; There isn't; complain and abort.
  164.     lxi    d,fullmsg
  165.     call    start
  166.     jmp    base
  167.  
  168. addent:
  169.     mov    m,c            ; Add an entry to table; first the PC,
  170.     inx    h
  171.     mov    m,b
  172.     inx    h
  173.     xra    a            ; then a count of 1.
  174.     mov    m,a
  175.     inx    h
  176.     mov    m,a
  177.     inx    h
  178.     mov    m,a
  179.     inx    h
  180.     inr    a
  181.     mov    m,a
  182.     inx    h
  183.  
  184.     shld    tbnext            ; Advance table end.
  185.  
  186. finis:
  187.     pop    psw
  188.     pop    b
  189.     pop    d
  190.     pop    h
  191.     ret                ; Return to target program
  192.  
  193. ;    Come here on a call to BIOS warmboot function or BDOS function 0.
  194. ; Reload CPROFILE in the lower TPA, and perform the analysis of the profile
  195. ; data gathered up in the TABLE area.
  196.  
  197. fakeboot:
  198.     lhld    realboot        ; Reset BIOS warm-boot transfer to
  199.     xchg                ; its original value.
  200.     lhld    base+1
  201.     inx    h
  202.     mov    m,e
  203.     inx    h
  204.     mov    m,d
  205.  
  206.     mvi    c, pstrng        ; Print a message to announce what's
  207.     lxi    d, rlodmsg        ; happening
  208.     call    bdos
  209.  
  210.     lxi    d, tbuff        ; Move command tail back in place
  211.     lxi    h, cmdline
  212.     mvi    c, 128
  213. mtail:    mov    a, m
  214.     stax    d
  215.     inx    h
  216.     inx    d
  217.     dcr    c
  218.     jnz    mtail
  219.  
  220.     mvi    c, openc        ; Re-open CPROFILE.COM
  221.     lxi    d, cprfcb
  222.     call    bdos
  223.     inr    a
  224.     jz    openerr
  225.     xra    a
  226.     sta    cprfcb+32        ; Zero current record index.
  227.  
  228. rloop:    lhld    loadorg            ; Get present loading origin
  229.     xchg
  230.     lxi    h, secsiz        ; Bump it by a sector for next time
  231.     dad    d
  232.     shld    loadorg
  233.     mvi    c, sdma            ; Set DMA pointer to loading origin
  234.     call    bdos
  235.  
  236.     mvi    c, reads        ; Read in a sector of CPROFILE.COM
  237.     lxi    d, cprfcb
  238.     call    bdos
  239.     ora    a
  240.     jz    rloop            ; Continue reading until EOF
  241.  
  242.     mvi    c, closec        ; Close CPROFILE.COM
  243.     lxi    d, cprfcb
  244.     call    bdos
  245.  
  246.     mvi    c, sdma            ; Reset default DMA address
  247.     lxi    d, tbuff
  248.     call    bdos
  249.  
  250.     jmp    tpa            ; Go enter reloaded copy of CPROFILE
  251.  
  252. openerr:                ; Couldn't reopen CPROFILE.COM
  253.     mvi    c, pstrng
  254.     lxi    d, opermsg
  255.     call    bdos
  256.     jmp    base
  257.  
  258. entrmsg:
  259.     db    '<<< Executing target program. >>>', CR, LF, '$'
  260. fullmsg:
  261.     db    CR, LF, '<<< Profile table is full.  Abandoning program. >>>'
  262.     db    '$'
  263. rlodmsg:
  264.     db    CR, LF, '<<< Reloading CPROFILE. >>>', CR, LF, '$'
  265. opermsg:
  266.     db    'Can''t open CPROFILE.COM; CPROFILE abandoned.$'
  267.  
  268. loadorg:
  269.     dw    tpa            ; Loading origin of CPROFILE
  270. cprfcb:
  271.     db    0, 'CPROFILE', 'COM', 0, 0, 0, 0
  272.     dw    0, 0, 0, 0, 0, 0, 0, 0    ; FCB for CPROFILE.COM
  273.     db    0, 0, 0, 0
  274.  
  275. table:                                ; Profile table starts here.
  276.  
  277. suptop:                    ; Top of the supervisor
  278.  
  279.     ENDFUNC        superv
  280.  
  281. ; CHAIN
  282.  
  283. ;        The following function is used to chain to the program being
  284. ;    analyzed.  It takes the following calling sequence:
  285.  
  286. ;        chain (argc, argv, entry);
  287.  
  288. ;    where argc and argv are the usual command parameters (argv [0] is the
  289. ;    name of the .COM file to load), and entry is the entry address of the
  290. ;    loaded program.  Entry would be 0x100 under normal circumstances, but
  291. ;    the CPROFILE run-time supervisor has a few unusual entry tasks to do.
  292.  
  293.     FUNCTION     chain
  294.  
  295.     EXTERNAL    nexecl
  296.  
  297.     call    arghak            ; Get the arguments
  298.     push    b
  299.  
  300.     lhld    arg3
  301.     push    h            ; Push the entry point address
  302.     lxi    h,0
  303.     push    h            ; Push the argv fence
  304.     lhld    arg1
  305.     xchg                ; Get DE = arg count, HL -> argv end
  306.     lhld    arg2
  307.     dad    d
  308.     dad    d
  309.  
  310. loop:    dcx    h
  311.     mov    a,m
  312.     dcx    h            ; Place an argument on stack
  313.     push    h
  314.     mov    l,m
  315.     mov    h,a
  316.     xthl
  317.  
  318.     dcx    d            ; Count down arguments until finished
  319.     mov    a, d
  320.     ora    e
  321.     jnz    loop
  322.  
  323. done:    call    nexecl            ; Go call NExecl to load the program
  324.     jmp    base            ; NEXECL return is a disaster.
  325.  
  326.     ENDFUNC    
  327.  
  328. ; NEXECL
  329.  
  330. ;        Derived from the EXECL function in the BDS `C' system library
  331. ;    (DEFF2C.CSM) copyright (c) 1983 by Leor Zolman.  Used by permission.
  332.  
  333. ;        This function is identical to the EXECL function in the BDS 'C'
  334. ;    system library with the single exception that it accepts an additional
  335. ;    argument following the list of command line arguments and the zero
  336. ;    terminator.  This argument is the address of a preinitialization entry
  337. ;    point to which the loader will transfer instead of entering the TPA
  338. ;    directly at 0x0100.
  339.  
  340.     FUNCTION    nexecl
  341.  
  342.     call    arghak
  343.     push    b
  344.     lhld    arg1                                              
  345.     xchg
  346.     lxi    h,-60    ;compute &nfcb for use here
  347.     dad    sp
  348.     push    h    ; save for much later (will pop    into BC)
  349.       push    h    ;make a few copies for local use below
  350.     push    h
  351.     call    setfcu    ;set up COM file for execl-ing
  352.     lda    usrnum
  353.     call    setusr    ;set destination user area
  354.     pop    h    ;get new fcb addr
  355.     lxi    b,9    ;set extension to COM
  356.     dad    b
  357.     mvi    m,'C'
  358.     inx    h
  359.     mvi    m,'O'
  360.     inx    h
  361.     mvi    m,'M'
  362.     pop    d    ;get new fcb addr again
  363.     mvi    c,openc    ;open the file for reading
  364.     call    bdos
  365.     call    rstusr    ;reset user number to previous
  366.     cpi    errorv
  367.     jnz    noerrr
  368. err:    pop    h
  369.     pop    b
  370.     jmp    error
  371.  
  372. noerrr:    lhld    arg2    ;any first parameter?
  373.     mov    a,h
  374.     ora    l
  375.     jnz    excl0
  376.     lxi    d,arg2    ;no...null out first default fcb slot
  377.     push    d
  378.     lxi    h,fcb
  379.     call    setfcb
  380.     pop    h
  381.     jmp    excl0a    ;and go null out 2nd fcb slot
  382.  
  383. excl0:    xchg        ;yes.. place into first default fcb slot
  384.     lxi    h,fcb
  385.     call    setfcb
  386.     lhld    arg3    ;any second parameter given?
  387.     mov    a,h
  388.     ora    l
  389.     jnz    excl0a
  390.     lxi    h,arg3
  391.  
  392. excl0a:    xchg        ;yes: stick it into second default fcb slot
  393.     lxi    h,fcb+16
  394.     call    setfcb    
  395.     lxi    d,tbuff+1   ;now construct command line:
  396.     xra    a    ;  zero tbuff+1 just in case there
  397.     stax    d    ;  are no arg strings
  398.     lxi    h,8    ;get pointer to 1st arg string in HL
  399.     dad    sp    ;   by offsetting 4 objects from the current SP
  400.     mvi    b,0    ;char count for com. line buf.
  401. excl1:    push    h    ;and construct command line
  402.     mov    a,m    ;get addr of next arg string pointer
  403.     inx    h
  404.     mov    h,m
  405.     mov    l,a    ;0000 indicates end of list.
  406.     ora    h    ;end of list?
  407.     jz    excl3
  408.  
  409.     mvi    a,' '    ;no. install next string
  410.     dcx    h
  411. excl2:    call    mpuc    ;convert to upper case for command line buffer
  412.     stax    d
  413.     inx    d
  414.     inr    b
  415.     inx    h
  416.     mov    a,m
  417.     ora    a    ;end of string?
  418.     jnz    excl2
  419.     pop    h    ;yes.
  420.     inx    h    ;bump param pointer
  421.     inx    h    
  422.     jmp    excl1    ;and go do next string
  423.  
  424. excl3:    pop    h    ;clean up stack
  425.     inx    h    ; point to last arg == entry address
  426.     inx    h
  427.     mov    a,m
  428.     inx    h
  429.     mov    h,m
  430.     mov    l,a
  431.     shld    enter+1    ; put entry address into loader.
  432.     mov    a,b    ;check for command buffer overflow
  433.     cpi    53h
  434.     jc    excl30    ;if no overflow, go load file
  435.     lxi    d,errmsg
  436.     mvi    c,9    ;else comlain and abort...
  437.     call    bdos
  438.     jmp    err
  439.  
  440. errmsg:    db    7,'EXECL: Command line overflow',cr,lf,'$'
  441.  
  442. excl30:    lxi    h,tbuff    ;set length of command line
  443.     mov    m,b    ;at location tbuff
  444.  
  445. excl3a:    lxi    d,code0    ;copy loader down to end of tbuff
  446.     lxi    h,tpa-42
  447.     mvi    b,42    ;length of loader
  448. excl4:    ldax    d
  449.     mov    m,a
  450.     inx    d
  451.     inx    h
  452.     dcr    b
  453.     jnz    excl4
  454.  
  455.     pop    b    ;get fcb pointer in BC
  456.             ;reset the SP:
  457.     lhld    base+6    ;get BDOS pointer in HL
  458.     lda    tpa    ;look at first op byte of run-time pkg
  459.     cpi    31h    ;begin with "lxi sp,"?
  460.     jnz    go0    ;if so, use the same value now...
  461.     lhld    tpa+1    ;else get special SP value
  462.     jmp    go1
  463.  
  464. go0:    cpi    21h    ;begin with "lxi h" (the NOBOOT sequence?)
  465.     jnz    go1    ;if not, just use the BDOS addr as top of memory
  466.     lxi    d,-2050    ;for NOBOOT, subtract 2100 from BDOS addr
  467.     dad    d    ;and make that the new SP
  468. go1:    sphl
  469.  
  470.     lxi    h,base
  471.     push    h    ;set base of ram as return addr
  472.     jmp    tpa-42    ;(go to `code0:')
  473.  
  474. mpuc:    cpi    61h    ;convert character in A to upper case
  475.     rc
  476.     cpi    7bh
  477.     rnc
  478.     sui    32
  479.     ret
  480.  
  481. ;
  482. ; This loader code is now: 42 bytes long.
  483. ;
  484.  
  485. code0:    lxi    d,tpa    ;destination address of new program
  486. code1:    push    d    ;push    dma addr
  487.     push    b    ;push    fcb pointer
  488.     mvi    c,sdma    ;set DMA address for new sector
  489.     call    bdos
  490.     pop    d    ;get pointer to working fcb in DE
  491.     push    d    ;and re-push    it
  492.     mvi    c,reads    ;read a sector
  493.     call    bdos
  494.     pop    b    ;restore fcb pointer into BC
  495.     pop    d    ;and dma address into DE
  496.     ora    a    ;end of file?
  497.     jz    tpa-8    ;if not, get next sector (goto `code2:')
  498.     mvi    c,sdma    ;reset DMA pointer
  499.     lxi    d,tbuff
  500.     call    bdos
  501. enter:    jmp    $-$    ;and go invoke the program
  502.  
  503. code2:    lxi    h,80h    ;bump dma address
  504.     dad d
  505.     xchg
  506.     jmp    tpa-39     ;and go loop (at code1)
  507.  
  508.     ENDFUNC
  509.  
  510.     end
  511.     jnz    go1    ;if no